package importxml;

import java.io.File;
import java.io.IOException;
import java.util.Vector;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.CharacterData;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class XmlParser {
	
	private String dir;
	private Vector<Course> courses;
	private Vector<Project> projects;
	private Icalendar calendar;
	private Vector<VCard> cards;
	
	public XmlParser(String dir) {
		courses = new Vector<Course>();
		projects = new Vector<Project>();
		cards = new Vector<VCard>();
		this.dir = dir;
	}
	
	public int getNumberOfCourses() {
		return courses.size();
	}
	
	public Course getCourse(int index) {
		return courses.get(index);
	}
	
	public int getNumberOfProjects() {
		return projects.size();
	}
	
	public Project getProject(int index) {
		return projects.get(index);
	}
	
	public int getNumberOfEvents() {
		return calendar.getNumberOfEvents();
	}
	
	public Event getEvent(int index) {
		return calendar.getEvent(index);
	}
	
	public int getNumberOfContacts() {
		return cards.size();
	}
	
	public VCard getContact(int index) {
		return cards.get(index);
	}
	
	public boolean parse() throws ParserConfigurationException, IOException {
		String filename = dir + "\\export.xml";
		File xml = new File(filename);
		DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
		Document doc;
		try {
			doc = builder.parse(xml);
		} catch (SAXException e) {
			return false;
		}
		NodeList nodes = doc.getElementsByTagName("courses");
		Element element = (Element) nodes.item(0);
		if (element != null) {
			NodeList courses = element.getElementsByTagName("course");
			for (int i = 0; i < courses.getLength(); i++) {
				Element course = (Element) courses.item(i);
				Course parsed = new Course(course, dir);
				if (parsed.isValid()) {
					this.courses.add(parsed);
				}
				else {
					return false;
				}
			}
		}
		nodes = doc.getElementsByTagName("projects");
		element = (Element) nodes.item(0);
		if (element != null) {
			NodeList projects = element.getElementsByTagName("project");
			for (int i = 0; i < projects.getLength(); i++) {
				Element project = (Element) projects.item(i);
				Project parsed = new Project(project, dir);
				if (parsed.isValid()) {
					this.projects.add(parsed);
				}
				else {
					return false;
				}
			}
		}
		nodes = doc.getElementsByTagName("calendar");
		element = (Element) nodes.item(0);
		if (element != null) {
			NodeList calendar = element.getElementsByTagName("file");
			element = (Element) calendar.item(0);
			if (element != null) {
				this.calendar = new Icalendar(dir + "\\" + getContent(element));
				if (!this.calendar.isValid()) {
					return false;
				}
			}
		}
		nodes = doc.getElementsByTagName("contacts");
		element = (Element) nodes.item(0);
		if (element != null) {
			NodeList contacts = element.getElementsByTagName("file");
			for (int i = 0; i < contacts.getLength(); i++) {
				Element contact = (Element) contacts.item(i);
				VCard card = new VCard(dir + "\\" + getContent(contact));
				if (card.isValid()) {
					File file = new File(dir + "\\" + getContent(contact));
					file.renameTo(new File(card.getEmail() + ".vcf"));
					cards.add(card);
				}
				else {
					return false;
				}
			}
		}
		nodes = doc.getElementsByTagName("extended");
		element = (Element) nodes.item(0);
		if (element != null) {
			nodes = element.getElementsByTagName("group5");
			element = (Element) nodes.item(0);
			if (element != null) {
				NodeList lessons = element.getElementsByTagName("lesson");
				if (!handleLessons(lessons)) {
					return false;
				}
				NodeList courses = element.getElementsByTagName("course");
				if (!handleCourses(courses)) {
					return false;
				}
				NodeList projects = element.getElementsByTagName("project");
				if (!handleProjects(projects)) {
					return false;
				}
				NodeList exams = element.getElementsByTagName("exam");
				if (!handleExams(exams)) {
					return false;
				}
				NodeList tasks = element.getElementsByTagName("task");
				if (!handleTasks(tasks)) {
					return false;
				}
			}
		}
		return true;
	}
	
	private boolean handleLessons(NodeList nodes) {
		for (int i = 0; i < nodes.getLength(); i++) {
			Element lesson = (Element) nodes.item(i);
			NodeList list = lesson.getElementsByTagName("start");
			Element element = (Element) list.item(0);
			String start = null;
			if (element != null) {
				start = getContent(element);
			}
			else {
				return false;
			}
			list = lesson.getElementsByTagName("summary");
			element = (Element) list.item(0);
			String summary = null;
			if (element != null) {
				summary = getContent(element);
			}
			else {
				return false;
			}
			int index = -1;
			for (int j = 0; j < calendar.getNumberOfEvents(); j++) {
				if (calendar.getEvent(j).getStart().equals(start) && calendar.getEvent(j).getSummary().equals(summary)) {
					index = j;
				}
			}
			if (index != -1) {
				calendar.getEvent(index).setLesson(true);
				list = lesson.getElementsByTagName("room");
				element = (Element) list.item(0);
				if (element != null) {
					calendar.getEvent(index).setRoom(getContent(element));
				}
				list = lesson.getElementsByTagName("day");
				element = (Element) list.item(0);
				if (element != null) {
					calendar.getEvent(index).setDayOfWeek(getContent(element));
				}
				list = lesson.getElementsByTagName("weeks");
				element = (Element) list.item(0);
				if (element != null) {
					calendar.getEvent(index).setNumberOfWeeks(getContent(element));
				}
				list = lesson.getElementsByTagName("course");
				element = (Element) list.item(0);
				if (element != null) {
					calendar.getEvent(index).setCourse(getContent(element));
				}
			}
			else {
				return false;
			}
		}
		return true;
	}
	
	private boolean handleCourses(NodeList nodes) {
		for (int i = 0; i < nodes.getLength(); i++) {
			Element course = (Element) nodes.item(i);
			NodeList list = course.getElementsByTagName("name");
			Element element = (Element) list.item(0);
			String name = null;
			if (element != null) {
				name = getContent(element);
			}
			else {
				return false;
			}
			int index = -1;
			for (int j = 0; j < courses.size(); j++) {
				if (courses.get(j).getName().equals(name)) {
					index = j;
				}
			}
			if (index != -1) {
				list = course.getElementsByTagName("year");
				element = (Element) list.item(0);
				if (element != null) {
					courses.get(index).setBeginYear(getContent(element));
				}
				list = course.getElementsByTagName("semester");
				element = (Element) list.item(0);
				if (element != null) {
					courses.get(index).setSemester(getContent(element));
				}
			}
			else {
				return false;
			}
		}
		return true;
	}
	
	private boolean handleProjects(NodeList nodes) {
		for (int i = 0; i < nodes.getLength(); i++) {
			Element project = (Element) nodes.item(i);
			NodeList list = project.getElementsByTagName("name");
			Element element = (Element) list.item(0);
			String name = null;
			if (element != null) {
				name = getContent(element);
			}
			else {
				return false;
			}
			int index = -1;
			for (int j = 0; j < projects.size(); j++) {
				if (projects.get(j).getName().equals(name)) {
					index = j;
				}
			}
			if (index != -1) {
				projects.get(index).setType("project");
				list = project.getElementsByTagName("grades");
				element = (Element) list.item(0);
				if (element != null) {
					projects.get(index).setGrades(getContent(element));
				}
				list = project.getElementsByTagName("done");
				element = (Element) list.item(0);
				if (element != null) {
					String done = getContent(element);
					if (done.equalsIgnoreCase("true")) {
						projects.get(index).setDone(true);
					}
					else if (done.equalsIgnoreCase("false")) {
						projects.get(index).setDone(false);
					}
					else {
						return false;
					}
				}
				list = project.getElementsByTagName("planning");
				element = (Element) list.item(0);
				if (element != null) {
					projects.get(index).setprojectPlanning(getContent(element));
				}
			}
			else {
				return false;
			}
		}
		return true;
	}
	
	private boolean handleTasks(NodeList nodes) {
		for (int i = 0; i < nodes.getLength(); i++) {
			Element task = (Element) nodes.item(i);
			NodeList list = task.getElementsByTagName("name");
			Element element = (Element) list.item(0);
			String name = null;
			if (element != null) {
				name = getContent(element);
			}
			else {
				return false;
			}
			int index = -1;
			for (int j = 0; j < projects.size(); j++) {
				if (projects.get(j).getName().equals(name)) {
					index = j;
				}
			}
			if (index != -1) {
				list = task.getElementsByTagName("grades");
				element = (Element) list.item(0);
				if (element != null) {
					projects.get(index).setGrades(getContent(element));
				}
				list = task.getElementsByTagName("done");
				element = (Element) list.item(0);
				if (element != null) {
					String done = getContent(element);
					if (done.equalsIgnoreCase("true")) {
						projects.get(index).setDone(true);
					}
					else if (done.equalsIgnoreCase("false")) {
						projects.get(index).setDone(false);
					}
					else {
						return false;
					}
				}
			}
			else {
				return false;
			}
		}
		return true;
	}
	
	private boolean handleExams(NodeList nodes) {
		for (int i = 0; i < nodes.getLength(); i++) {
			Element exam = (Element) nodes.item(i);
			NodeList list = exam.getElementsByTagName("name");
			Element element = (Element) list.item(0);
			String name = null;
			if (element != null) {
				name = getContent(element);
			}
			int index = -1;
			for (int j = 0; j < projects.size(); j++) {
				if (projects.get(j).getName().equals(name)) {
					index = j;
				}
			}
			if (index != -1) {
				projects.get(index).setType("exam");
				list = exam.getElementsByTagName("grades");
				element = (Element) list.item(0);
				if (element != null) {
					projects.get(index).setGrades(getContent(element));
				}
				list = exam.getElementsByTagName("done");
				element = (Element) list.item(0);
				if (element != null) {
					String done = getContent(element);
					if (done.equalsIgnoreCase("true")) {
						projects.get(index).setDone(true);
					}
					else if (done.equalsIgnoreCase("false")) {
						projects.get(index).setDone(false);
					}
					else {
						return false;
					}
				}
				list = exam.getElementsByTagName("room");
				element = (Element) list.item(0);
				if (element != null) {
					projects.get(index).setExamRoom(getContent(element));
				}
				list = exam.getElementsByTagName("hours");
				element = (Element) list.item(0);
				if (element != null) {
					projects.get(index).setExamHours(getContent(element));
				}
				list = exam.getElementsByTagName("type");
				element = (Element) list.item(0);
				if (element != null) {
					projects.get(index).setExamType(getContent(element));
				}
				list = exam.getElementsByTagName("oral");
				element = (Element) list.item(0);
				if (element != null) {
					String oral = getContent(element);
					if (oral.equalsIgnoreCase("true")) {
						projects.get(index).setExamOral(true);
					}
					else if (oral.equalsIgnoreCase("false")) {
						projects.get(index).setExamOral(false);
					}
					else {
						return false;
					}
				}
				
			}
			else {
				return false;
			}
		}
		return true;
	}
	
	private String getContent(Element e) {
		Node child = e.getFirstChild();
		if (child instanceof CharacterData) {
			CharacterData cd = (CharacterData) child;
			return cd.getData();
		}
		return "?";
	}
	
}
